package com.zyl.forkjoin;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

/**
 * @author zhaoyl
 * @date 2024/5/17 18:03
 * @description 说明
 */
public class Test {

    private static Long start =1L;
    private static Long end=1_0000_0000L;//10亿

   //测试技术效率
    public static void main(String[] args) {
        //test1();//执行时间->790
       // test2();//执行时间->319
        test3();//执行时间->72
    }

    //求和计算方式1,累加
    public static void test1(){
        Long startTime = System.currentTimeMillis();

        Long sum =0L;
        for (Long i=start;i<=end;i++){
            sum +=i;
        }
        System.out.println("sum="+sum);
        Long endTime = System.currentTimeMillis();
        System.out.println("执行时间->"+(endTime-startTime));

    }
    //求和计算方式2,ForkJoin
    public static void test2(){
        Long sum = 0L;
        Long startTime = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();

        /*ForkJoinPool构造方法有四个参数：
        parallelism：期望并发数。默认会使用Runtime.getRuntime().availableProcessors()的值
        factory：创建ForkJoin工作线程的工厂，默认为defaultForkJoinWorkerThreadFactory
        handler：执行任务时遇到不可恢复的错误时的处理程序，默认为null
        asyncMode：工作线程获取任务使用FIFO(先进先出)模式还是LIFO(后进先出)模式，默认为LIFO*/

        ForkJoinTask<Long> task = new ForkjoinDemo(start,end);

/*        异步执行
        forkjoinPool.execute(task);无返回结果
        同步执行
        forkjoinPool.invoke(task);等待返回结果
        异步执行，通过Future获取结果
        forkjoinPool.submit(task);*/

        ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务

     /*   ForkJoinTask是对于在ForkJoinPool中运行任务的抽象类定义。
        JDK为我们提供了三种特定类型的ForkJoinTask父类供我们自定义时继承使用。
        RecursiveAction：子任务不返回结果
        RecursiveTask：子任务返回结果
        CountedCompleter：在任务完成执行后会触发执行*/

        try {
             sum = submit.get();//获取值，会阻塞等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("sum="+sum);
        Long endTime = System.currentTimeMillis();
        System.out.println("执行时间->"+(endTime-startTime));

    }
    //求和计算方式3,stream并行流（实际上Stream并行流本质上就是一个帮你fork/join 后的API）
    public static void test3(){
        Long startTime = System.currentTimeMillis();
        //stream并行流
        long sum = LongStream.rangeClosed(start, end).parallel().reduce(0, Long::sum);
        System.out.println("sum="+sum);
        Long endTime = System.currentTimeMillis();
        System.out.println("执行时间->"+(endTime-startTime));

    }
}
